/*
 *
 *  Copyright (C) 2010 Tal Eisenberg
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package tal.drivechain.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import tal.drivechain.module.properties.ColorParser;

/**
 * Heavily borrowed from http://www.dreamfabric.com/java/knob/knob.html
 *
 * @author eisental
 */
public class CircularDragSlider extends DragSlider {

    boolean negative;
    private Color color;
    private final static Dimension MIN_SIZE = new Dimension(30, 30);
    private final static Dimension PREF_SIZE = new Dimension(60, 60);
    private final static double START = 225;
    private final static double LENGTH = 270;
    private final static double START_ANG = (START / 360) * Math.PI * 2;
    private final static double LENGTH_ANG = (LENGTH / 360) * Math.PI * 2;

    private final static RenderingHints AALIAS =
            new RenderingHints(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    private int size;
    private Color xor;

    public CircularDragSlider(double value, double maxValue, double minValue, double scale, Color color, boolean negative) {
        super(value, maxValue, minValue, scale);

        setPreferredSize(PREF_SIZE);
        setColor(color);
        this.negative = negative;

    }

    public CircularDragSlider() {
        this(0, 100, 0, 1, Color.CYAN, false);
    }

    @Override
    public void mousePressed(MouseEvent e) {
        super.mousePressed(e);
        requestFocus();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int width = getWidth();
        int height = getHeight();
        size = Math.min(width, height) - 22;

        if (g instanceof Graphics2D) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setBackground(getParent().getBackground());
            g2d.addRenderingHints(AALIAS);
        }


        // outer circle
        g.setColor(color);
        g.fillArc(10, 10, size, size, 315, 270);

        // black area
        g.setColor(Color.black);
        g.drawOval(10, 10, size, size);
        g.fillOval(14, 14, size-8, size-8);

        // inner circle
        g.setColor(color.darker());
        int s2 = (int) Math.max(size / 6, 6);
        g.drawArc(10 + s2, 10 + s2, size - s2 * 2, size - s2 * 2, 315, 270);

        double ang = calcAng();

        // pointer
        g.setColor(xor);
        int x = 10 + size / 2 + (int) (size / 2 * Math.cos(ang));
        int y = 10 + size / 2 - (int) (size / 2 * Math.sin(ang));
        g.drawLine(10 + size / 2, 10 + size / 2, x, y);

        int dx = (int) (2 * Math.sin(ang));
        int dy = (int) (2 * Math.cos(ang));
        g.drawLine(10 + dx + size / 2, 10 + dy + size / 2, x, y);
        g.drawLine(10 - dx + size / 2, 10 - dy + size / 2, x, y);




    }

    @Override
    public Dimension getPreferredSize() {
        return PREF_SIZE;
    }

    @Override
    public Dimension getMinimumSize() {
        return MIN_SIZE;
    }

    public void setColor(Color color) {
        this.color = color;
        this.xor = ColorParser.xor(color);
        repaint();
    }

    public Color getColor() {
        return color;
    }

    public void setNegative(boolean b) {
        this.negative = b;
        repaint();
    }

    public boolean isNegative() {
        return negative;
    }

    private double calcAng() {
        double val = (getValue() - min)/(max-min);
        return START_ANG - LENGTH_ANG * val;
    }
}
